package com.iwinding.ladygg.utils;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore.MediaColumns;
import android.text.TextUtils;
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * Bitmap与DrawAble与byte[]与InputStream之间的转换工具类
 *
 * @author Administrator
 */
public class ImageFormatTools {
    public static final String SF_DIR = Environment
            .getExternalStorageDirectory() + "/shunfeng";
    public static final String ImageDir = SF_DIR + "/Image";

    public static final float CAMERA_DISPLAY_WIDTH_MEDIUM = 480f;
    public static final float CAMERA_DISPLAY_HEIGHT_MEDIUM = 800f;
    private final int IAMGE_MAX_SIZE = 120;// 图片大小的最大值，单位KB

    // 服务器上传限制最大图片300k
    public final int SERVER_IMAGE_SIZE_MAX = 300 * 1024;

    private static ImageFormatTools tools = new ImageFormatTools();

    public static ImageFormatTools getInstance() {
        if (tools == null) {
            tools = new ImageFormatTools();
            return tools;
        }
        return tools;
    }

    // 将byte[]转换成InputStream
    public InputStream Byte2InputStream(byte[] b) {
        ByteArrayInputStream bais = new ByteArrayInputStream(b);
        return bais;
    }

    // 将InputStream转换成byte[]
    public byte[] InputStream2Bytes(InputStream is) {
        String str = "";
        byte[] readByte = new byte[1024];
        try {
            while ((is.read(readByte, 0, 1024)) != -1) {
                str += new String(readByte).trim();
            }
            return str.getBytes();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 将Bitmap转换成InputStream
    public InputStream Bitmap2InputStream(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        InputStream is = new ByteArrayInputStream(baos.toByteArray());
        return is;
    }

    // 将Bitmap转换成InputStream
    public InputStream Bitmap2InputStream(Bitmap bm, int quality) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        InputStream is = new ByteArrayInputStream(baos.toByteArray());
        return is;
    }

    // 将InputStream转换成Bitmap
    public Bitmap InputStream2Bitmap(InputStream is) {
        return BitmapFactory.decodeStream(is);
    }

    // 将InputStream转换成Bitmap
    public Bitmap InputStream2Bitmap(InputStream is, BitmapFactory.Options opts) {
        return BitmapFactory.decodeStream(is, null, opts);
    }

    // Drawable转换成InputStream
    public InputStream Drawable2InputStream(Drawable d) {
        Bitmap bitmap = this.drawable2Bitmap(d);
        return this.Bitmap2InputStream(bitmap);
    }

    // InputStream转换成Drawable
    public Drawable InputStream2Drawable(InputStream is) {
        Bitmap bitmap = this.InputStream2Bitmap(is);
        return this.bitmap2Drawable(bitmap);
    }

    // Drawable转换成byte[]
    public byte[] Drawable2Bytes(Drawable d) {
        Bitmap bitmap = this.drawable2Bitmap(d);
        return this.Bitmap2Bytes(bitmap);
    }

    // byte[]转换成Drawable
    public Drawable Bytes2Drawable(byte[] b) {
        Bitmap bitmap = this.Bytes2Bitmap(b);
        return this.bitmap2Drawable(bitmap);
    }

    // Bitmap转换成byte[]
    public byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        return baos.toByteArray();
    }

    // byte[]转换成Bitmap
    public Bitmap Bytes2Bitmap(byte[] b) {
        if (b == null || b.length == 0)
            return null;
        else
            return BitmapFactory.decodeByteArray(b, 0, b.length);
    }

    // byte[]转换成Bitmap
    //width 最大图片宽度
    //height 最大图片高度
    public Bitmap Bytes2Bitmap(byte[] bytes, int maxWidth, int maxHeight) {
        if (bytes == null || bytes.length == 0)
            return null;
        //对于图片的二次采样,主要得到图片的宽与高
        int width = 0;
        int height = 0;
        int sampleSize = 1; //默认缩放为1
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;  //仅仅解码边缘区域
        //如果指定了inJustDecodeBounds，decodeByteArray将返回为空
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
        //得到宽与高
        height = options.outHeight;
        width = options.outWidth;
        if (height > maxHeight || width > maxWidth) {
            final int heightRatio = Math.round((float) height
                    / (float) maxHeight);
            final int widthRatio = Math.round((float) width / (float) maxWidth);
            sampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;
        }
        LogUtil.i("sampleSize", sampleSize + ",,");
        //不再只加载图片实际边缘
        options.inJustDecodeBounds = false;
        //并且制定缩放比例
        options.inSampleSize = sampleSize;
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    }

    // Drawable转换成Bitmap
    public Bitmap drawable2Bitmap(Drawable drawable) {
        Bitmap bitmap = Bitmap
                .createBitmap(
                        drawable.getIntrinsicWidth(),
                        drawable.getIntrinsicHeight(),
                        drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
                                : Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    // Bitmap转换成Drawable
    public Drawable bitmap2Drawable(Bitmap bitmap) {
        BitmapDrawable bd = new BitmapDrawable(bitmap);
        Drawable d = bd;
        return d;
    }

    /**
     * 图片文件转成字节数组
     *
     * @param file
     * @return
     */
    public byte[] file2Bytes(File file) {
        if (file == null || !file.exists() || !file.isFile())
            return null;

        Bitmap bitmap = null;
        try {
            bitmap = InputStream2Bitmap(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            bitmap = null;
        }

        if (bitmap == null)
            return null;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

        return baos.toByteArray();
    }

    /**
     * 图片文件转成字节数组
     *
     * @param picPath
     * @return
     */
    public byte[] file2Bytes(String picPath) {
        if (TextUtils.isEmpty(picPath))
            return null;

        return file2Bytes(new File(picPath));
    }

    public Bitmap loadBitmapFromRes(Resources resources, int resId,
                                    BitmapFactory.Options opts) {
        return InputStream2Bitmap(resources.openRawResource(resId), opts);
    }

    /**
     * 以最省内存的方式读取本地资源的图片
     *
     * @param resources
     * @param resId
     * @return
     */
    public Bitmap loadBitmapFromRes(Resources resources, int resId) {
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = Config.RGB_565;
        opt.inPurgeable = true;
        opt.inInputShareable = true;
        return InputStream2Bitmap(resources.openRawResource(resId), opt);
    }

    /**
     * 获取文件的MD5值，为了和IOS一致，必须将小写字母变成大写
     *
     * @param file
     * @return
     */
    public String getFileMD5(File file) {
        if (file == null || !file.exists() || !file.isFile())
            return null;

        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("md5");
            in = new FileInputStream(file);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16).toUpperCase();
    }

    /**
     * 获取图片压缩后在SD卡的路径
     *
     * @param name
     * @return
     */
    public String getPicPath(String name) {
        if (TextUtils.isEmpty(name))
            return null;

        return ImageDir + "/" + name + ".jpg";
    }

    /**
     * 图片的质量压缩方法
     *
     * @param image
     * @return
     */
    private Bitmap compressBitmapQuality(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;

        while (baos.toByteArray().length > 1024 * IAMGE_MAX_SIZE && options > 0) { // 循环判断如果压缩后图片是否大于限定尺寸,大于继续压缩
            baos.reset();// 重置baos即清空baos
            options -= 10;// 每次都减少10
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
        }

        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    public String compressPicture(String picPath) {
        if (TextUtils.isEmpty(picPath) || !verifyImageDir())
            return null;

        Bitmap bitmap = null;
        int size;
        if (TextUtils.isEmpty(picPath)) {
            return null;
        }

        // 获取原图比例大小
        String compressedPicPath = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        int o_with;
        int o_height;
        ByteArrayOutputStream baos = null;
        ByteArrayOutputStream bs = null;
        try {
            BitmapFactory.decodeFile(picPath, options);
            o_with = options.outWidth;
            o_height = options.outHeight;
            if (o_with > CAMERA_DISPLAY_WIDTH_MEDIUM || o_height > CAMERA_DISPLAY_HEIGHT_MEDIUM) {
                final int heightRatio = Math.round((float) o_height
                        / CAMERA_DISPLAY_HEIGHT_MEDIUM);
                final int widthRatio = Math.round((float) o_with / CAMERA_DISPLAY_WIDTH_MEDIUM);
                options.inSampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;
            }
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeFile(picPath, options);

            baos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            size = baos.toByteArray().length;

            if (size > SERVER_IMAGE_SIZE_MAX) {
                int tempSize = (int) Math.sqrt((double) (size / SERVER_IMAGE_SIZE_MAX)) + 1;
                options.inSampleSize = tempSize;
                options.inJustDecodeBounds = false;
                bitmap = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()), null, options);

                bs = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bs);
                size = bs.toByteArray().length;

                while (size > SERVER_IMAGE_SIZE_MAX) { // do compress again
                    tempSize = 2 * tempSize;
                    options.inSampleSize = tempSize;

                    bitmap = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()), null, options);

                    bs.reset();
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bs);
                    size = bs.toByteArray().length;
                }
            }


            if (bitmap != null) {
                // 保存压缩后的图片到SD卡
                compressedPicPath = getPicPath(getFileMD5(new File(picPath)));
                boolean ret = saveBitmap2SdCard(bitmap, compressedPicPath);
                if (!ret) {
                    compressedPicPath = null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bs != null) {
                try {
                    bs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bitmap != null) {
                bitmap.recycle();
                bitmap = null;
            }
        }

        return compressedPicPath;
    }

    /**
     * 压缩图片的尺寸
     *
     * @param path ：图片的路径名
     * @return
     */
    public Bitmap getCompressedBitmap(String path, float displayWidth,
                                      float displayHeight) {
        Bitmap bitmap = null;
        if (TextUtils.isEmpty(path) || displayWidth < 1 || displayHeight < 1) {
            return null;
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        // 获取原图比例大小
        try {
            bitmap = BitmapFactory.decodeFile(path, options);// 此时返回bitmap为空
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        int w = options.outWidth;
        int h = options.outHeight;
        int be = 1;
        if (w > h && w > displayWidth) {
            be = (int) (options.outWidth / displayWidth);
        } else if (w < h && h > displayHeight) {
            be = (int) (options.outHeight / displayHeight);
        }
        if (be <= 0) {
            be = 1;
        }
//		int wRatio = options.outWidth / displayWidth;
//		int hRatio = options.outHeight / displayHeight;

        // 重新读入图片，把options.inJustDecodeBounds设为false
        options.inJustDecodeBounds = false;
        options.inSampleSize = be;
        options.inPreferredConfig = Config.RGB_565;
        options.inPurgeable = true;
        options.inInputShareable = true;

        // 如果超出指定大小，则缩小相应的比例
//		if (wRatio > 1 || hRatio > 1) {
//			if (wRatio > hRatio) {
//				options.inSampleSize = wRatio;
//			} else {
//				options.inSampleSize = hRatio;
//			}
//		}

        try {
            // 根据压缩比例获取压缩后的bitmap
            bitmap = BitmapFactory.decodeFile(path, options);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return compressBitmapQuality(bitmap);
    }

    /**
     * 保存图片(Bitmap)到SD卡
     *
     * @param bitmap
     * @param path
     * @return
     * @throws IOException
     */
    public boolean saveBitmap2SdCard(Bitmap bitmap, String path)
            throws IOException {
        boolean isSuccess = false;
        if (TextUtils.isEmpty(path) || !verifyImageDir()) {
            return false;
        }
        File f = new File(path);
        f.createNewFile();
        FileOutputStream fOut = null;
        try {
            fOut = new FileOutputStream(f);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            isSuccess = false;
        }
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
        try {
            if (fOut != null) {
                fOut.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
            isSuccess = false;
        }
        try {
            if (fOut != null) {
                fOut.close();
            }
            isSuccess = true;
        } catch (IOException e) {
            e.printStackTrace();
            isSuccess = false;
        }

        return isSuccess;
    }

    public String getPathFromUri(Context context, Uri uri) {
        String path = null;
        ContentResolver cr = context.getContentResolver();
        String[] proj = {MediaColumns.DATA};

        Cursor cursor = cr.query(uri, proj, null, null, null);
        if (cursor == null || cursor.getColumnCount() == 0)
            return null;

        int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
        cursor.moveToFirst();
        path = cursor.getString(column_index);
        if (!cursor.isClosed()) {
            cursor.close();
        }

        return path;
    }

    /**
     * 获取当前屏幕的截图,返回图片路径
     *
     * @param window
     * @return
     */
    public String getScreenshotImgPath(Window window) {
        // 构建Bitmap
        WindowManager windowManager = window.getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        Bitmap bitmap = Bitmap.createBitmap(display.getWidth(),
                display.getHeight(), Config.ARGB_8888);

        // 获取屏幕
        View decorview = window.getDecorView();

        decorview.setDrawingCacheEnabled(true);
        bitmap = decorview.getDrawingCache();

        // 图片存储路径
        String filePath = getPicPath(String.valueOf(System.currentTimeMillis()));

        // 保存Bitmap
        try {
            boolean ret = saveBitmap2SdCard(bitmap, filePath);
            if (!ret)
                filePath = null;
        } catch (IOException e) {
            e.printStackTrace();
            filePath = null;
        }

        return filePath;
    }


    /**
     * 获取当前屏幕的截图,返回图片路径
     *
     * @param window
     * @return
     */
    public String getScreenshotImgPath(Window window, int statusBarHeight, int height) {
        // 构建Bitmap
        WindowManager windowManager = window.getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        // 获取屏幕
        View decorview = window.getDecorView();
        decorview.setDrawingCacheEnabled(true);
        decorview.buildDrawingCache();
        Bitmap bitmap = decorview.getDrawingCache();

        // bitmap = Bitmap.createBitmap(bitmap, 0, statusBarHeight,display.getWidth(), height );
        bitmap = Bitmap.createBitmap(bitmap, 0, statusBarHeight,
                display.getWidth(), bitmap.getHeight() - statusBarHeight);

        decorview.destroyDrawingCache();

        // 图片存储路径
        String filePath = getPicPath(String.valueOf(System.currentTimeMillis()));

        // 保存Bitmap
        try {
            boolean ret = saveBitmap2SdCard(bitmap, filePath);
            if (!ret)
                filePath = null;
        } catch (IOException e) {
            e.printStackTrace();
            filePath = null;
        }

        return filePath;
    }


    /**
     * @param filePath   原图路径
     * @param edgeLength 希望得到的正方形部分的边长
     * @return 缩放截取正中部分后的位图。
     */
    public Bitmap centerSquareBitmap(String filePath, int edgeLength) {
        if (TextUtils.isEmpty(filePath) || edgeLength < 1)
            return null;

        Bitmap bitmap = getCompressedBitmap(filePath, edgeLength, edgeLength);
        if (bitmap == null)
            return null;

        return centerSquareBitmap(bitmap, edgeLength);
    }

    /**
     * @param bitmap     原图
     * @param edgeLength 希望得到的正方形部分的边长
     * @return 缩放截取正中部分后的位图。
     */
    public Bitmap centerSquareBitmap(Bitmap bitmap, int edgeLength) {
        if (bitmap == null || edgeLength < 1)
            return null;

        Bitmap result = bitmap;
        int widthOrg = bitmap.getWidth();
        int heightOrg = bitmap.getHeight();

        // 压缩到一个最小长度是edgeLength的bitmap
        int longerEdge = edgeLength * Math.max(widthOrg, heightOrg) / Math
                .min(widthOrg, heightOrg);

        int scaledWidth = widthOrg > heightOrg ? longerEdge : edgeLength;
        int scaledHeight = widthOrg > heightOrg ? edgeLength : longerEdge;
        Bitmap scaledBitmap;

        try {
            scaledBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth,
                    scaledHeight, true);
        } catch (Exception e) {
            return null;
        }

        // 从图中截取正中间的正方形部分。
        int xTopLeft = (scaledWidth - edgeLength) / 2;
        int yTopLeft = (scaledHeight - edgeLength) / 2;

        try {
            result = Bitmap.createBitmap(scaledBitmap, xTopLeft, yTopLeft,
                    edgeLength, edgeLength);
            scaledBitmap.recycle();
        } catch (Exception e) {
            return null;
        }

        return result;
    }

    public boolean verifyImageDir() {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_UNMOUNTED))
            return false;

        // 先判断目录是否存在
        File dir = new File(ImageDir);
        if (!dir.exists()) { // 不存在则创建
            dir.mkdirs();
        }

        return true;
    }

    /**
     * 将图片变为圆角
     *
     * @param bitmap 原Bitmap图片
     * @param pixels 图片圆角的弧度(单位:像素(px))
     * @return 带有圆角的图片(Bitmap 类型)
     */
    public Bitmap toRoundCorner(Bitmap bitmap, int pixels) {

        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = pixels;

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }

}